	var Cryptokit=function Cryptokit(browser) {
	    this.browser = browser;
	};
	
	Cryptokit.subjectDNFilter="crcrfsp";//证书主题DN
	Cryptokit.issuerDNFilter="";
	Cryptokit.serialNumFilter="";
	Cryptokit.cspFilter="";
	
	Cryptokit.edgeExtension = "gkoeajppklgjbhjlbccjolaacdaajnhh";
	Cryptokit.productID = "com.cfca.cryptokit.crcrfsp";

	Cryptokit.extensionName = Cryptokit.productID + ".extension";
	Cryptokit.reqEventName  = Cryptokit.productID + ".request";
	Cryptokit.respEventName = Cryptokit.productID + ".response";
	
	Cryptokit.p11Name="CFCA_UKEY_P11.dll";//新KEY
	Cryptokit.algorithm="SHA-1";//加密算法

	Cryptokit.Browser = {
	    IE:      "Internet Explorer",
	    Edge:    "Edge",
	    Edg:     "Edge(Chromium)",
	    Chrome:  "Chrome",
	    Safari:  "Safari",
	    Firefox: "Firefox",
	};

	function GenerateRandomId() {
	    var charstring = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890';
	    var maxPos = charstring.length;
	    var randomId = '';
	    for (i = 0; i < 10; i++) {
	        randomId += charstring.charAt(Math.floor(Math.random() * maxPos));
	    }
	    return randomId;
	}

	// Encapsulate Chrome sendMessage callback to Promise
	Cryptokit.SendMessageforChrome = function(request) {
	    return new Promise( function (resolve, reject) {
	        chrome.runtime.sendMessage(Cryptokit.chromeExtension, request, function (response) {
				if (response) {
					if(0 == response.errorcode){ 
	                    resolve(response);                                    
					}
					else{
	                    reject(response);
					}
				}
				else {
				    var result = new Object();
				    result.errorcode = 1;
				    result.result = chrome.runtime.lastError.message;
				    reject(result);
				}
			});
	    });
	}

	// Encapsulate Chrome sendMessage callback to Promise
	Cryptokit.SendMessageforEdge = function(request) {
	    return new Promise( function (resolve, reject) {
	    	
	    	if(chrome.runtime == 'undefined' || chrome.runtime == undefined || chrome.runtime == null){
	    		var result = new Object();
	    		result.errorcode = 1;
			    reject(result);
	    	}else{
	    		chrome.runtime.sendMessage(Cryptokit.edgeExtension, request, function (response) {
					if (response) {
						if(0 == response.errorcode){ 
		                    resolve(response);                                    
						}
						else{
		                    reject(response);
						}
					}
					else {
					    var result = new Object();
					    result.errorcode = 1;
					    result.result = chrome.runtime.lastError.message;
					    reject(result);
					}
				});
	    	}
	    });
	}


	// Encapsulate Edge&Firefox event to Promise
	Cryptokit.SendMessagebyEvent = function(request) {
	    var event = new CustomEvent(Cryptokit.reqEventName, { detail: request });
	    document.dispatchEvent(event);

	    return new Promise( function (resolve, reject) {
		
		    var responseEventName = Cryptokit.respEventName;
		    if(request.funcInfo != undefined && request.funcInfo.randomId != undefined)
				responseEventName += ("." + request.funcInfo.randomId);
				
	        document.addEventListener(responseEventName, function CallBack(e) {
	            document.removeEventListener(e.type, CallBack);
	            var eJson = JSON.parse(e.detail);
	            if (null != eJson && 0 == eJson.errorcode) {
	                resolve(eJson);
	            }
	            else {
	                reject(eJson);
	            }
	        }, false);
	    });
	}


	Cryptokit.SendMessage = function(browser, requestJSON) {
	    if (Cryptokit.Browser.Chrome == browser) {
	        return Cryptokit.SendMessageforChrome(requestJSON);
	    }
	    else if(Cryptokit.Browser.Edg == browser) {
	        return Cryptokit.SendMessageforEdge(requestJSON);
	    }
	    else {
	        return Cryptokit.SendMessagebyEvent(requestJSON);
	    }
	}


	Cryptokit.checkExtension = function(browser) {
	    return new Promise(function (resolve, reject) {
	        var result = new Object();
	        
	        if (Cryptokit.Browser.Chrome == browser || Cryptokit.Browser.Edg == browser) {console.log("chrome.runtime="+chrome.runtime);
	            if(chrome.runtime) {
	                resolve(browser);
	            }else{
	                result.errorcode = 2;
	                result.result = "Extension does not exist!";
	                reject(result);	
	           }
	        }else if (Cryptokit.Browser.Edge == browser || Cryptokit.Browser.Firefox == browser) {
	            if (document.getElementById(Cryptokit.extensionName)) {
	                resolve(browser);
	            }else {
	                result.errorcode = 2;
	                result.result = "Extension does not exist!";
	                reject(result);	            
	           }
	        }else{
                result.errorcode = 3;
                result.result = "Only support Chrome/Edge/Firefox";
                reject(result);        
	        }
	    });
	}
		
	Cryptokit.prototype.init = function () {

		var res = {
            name: "",
            version: "",
        };
        var reg;
        var userAgent = self.navigator.userAgent;

        if (reg = /edge\/([\d\.]+)/i.exec(userAgent)) {
            res.name = "Edge";
            res.version = reg[1];
        }
        else if (reg = /edg\/([\d\.]+)/i.exec(userAgent)) {
            res.name = "Edge(Chromium)";
            res.version = reg[1];
        }
        
        if(res.name != ""){
        	var browser = res.name;
    	    return Cryptokit.checkExtension(browser)
    	        .then(function (browser) {
    	            var request = new Object();
    	            request.action = "connect";
    	            request.host = Cryptokit.productID;
    	            console.log("Cryptokit init finish");
    	            return Cryptokit.SendMessage(browser, request);
    	        });
        }
	}


	Cryptokit.prototype.uninit = function () {

	    var request = new Object();                   
	    request.action = "disconnect";
	    request.host = Cryptokit.productID;

	    return Cryptokit.SendMessage(this.browser, request);
	}


	Cryptokit.prototype.getExtensionVersion = function ( ) {

	    var request = new Object();
	    var funcInfo = new Object();
	    
	    funcInfo.function = "getExtensionVersion";
	    funcInfo.params = null;
	    request.action = "getExtensionVersion";
	    request.funcInfo = funcInfo;

	    return Cryptokit.SendMessage(this.browser, request);
	}


	Cryptokit.prototype.getHostVersion = function () {

	    var request = new Object();
	    var funcInfo = new Object();
	    var randomId = GenerateRandomId();
	           
	    funcInfo.function = "GetVersion";
	    funcInfo.params = null;
	    funcInfo.randomId = randomId;
	       
	    request.action = "invoke";
	    request.funcInfo = funcInfo;

	    return Cryptokit.SendMessage(this.browser, request);
	}


	Cryptokit.prototype.SelectCertificate = function () {

	    var request = new Object();
	    var funcInfo = new Object();
	    var paramArr = new Array();
	    var randomId = GenerateRandomId();
	    
	    paramArr.push(Cryptokit.subjectDNFilter);
	    paramArr.push(Cryptokit.issuerDNFilter);
	    paramArr.push(Cryptokit.serialNumFilter);
	    paramArr.push(Cryptokit.cspFilter);
	       
	    funcInfo.function = "SelectCertificate";
	    funcInfo.params = paramArr;
	    funcInfo.randomId = randomId;
	       
	    request.action = "invoke";
	    request.funcInfo = funcInfo;
	    
	    return Cryptokit.SendMessage(this.browser, request);
	}


	Cryptokit.prototype.GetSignCertInfo = function (bstrInfoType) {

	    var request = new Object();
	    var funcInfo = new Object();
	    var paramArr = new Array();
	    var randomId = GenerateRandomId();

	    paramArr.push(bstrInfoType);

	    funcInfo.function = "getSignCertInfo";
	    funcInfo.params = paramArr;
	    funcInfo.randomId = randomId;

	    request.action = "invoke";
	    request.funcInfo = funcInfo;

	    return Cryptokit.SendMessage(this.browser, request);
	}


	Cryptokit.prototype.SignMsgPKCS7Detached = function (bstrSourceData, bstrHashAlg) {

	    var request = new Object();
	    var funcInfo = new Object();
	    var paramArr = new Array();
	    var randomId = GenerateRandomId();

	    paramArr.push(bstrSourceData);
	    paramArr.push(bstrHashAlg);

	    funcInfo.function = "SignMsgPKCS7Detached";
	    funcInfo.params = paramArr;
	    funcInfo.randomId = randomId;

	    request.action = "invoke";
	    request.funcInfo = funcInfo;

	    return Cryptokit.SendMessage(this.browser, request);
	}


	Cryptokit.prototype.SignHashMsgPKCS7Detached = function (bstrSourceData, bstrHashAlg) {

	    var request = new Object();
	    var funcInfo = new Object();
	    var paramArr = new Array();
	    var randomId = GenerateRandomId();

	    paramArr.push(bstrSourceData);
	    paramArr.push(bstrHashAlg);

	    funcInfo.function = "SignHashMsgPKCS7Detached";
	    funcInfo.params = paramArr;
	    funcInfo.randomId = randomId;

	    request.action = "invoke";
	    request.funcInfo = funcInfo;

	    return Cryptokit.SendMessage(this.browser, request)
	}
	

	Cryptokit.prototype.GetSealImage = function () {

	    var request = new Object();
	    var funcInfo = new Object();
	    var paramArr = new Array();
	    var randomId = GenerateRandomId();

	    paramArr.push("CFCA_UKEY_P11.dll");

	    funcInfo.function = "GetSealImage";
	    funcInfo.params = paramArr;
	    funcInfo.randomId = randomId;

	    request.action = "invoke";
	    request.funcInfo = funcInfo;

	    return Cryptokit.SendMessage(this.browser, request);
	}
	
	


	Cryptokit.prototype.GetVersion = function () {

	    var request = new Object();
	    var funcInfo = new Object();
	    var randomId = GenerateRandomId();
	       
	    funcInfo.function = "GetVersion";
	    funcInfo.params = null;
	    funcInfo.randomId = randomId;
	       
	    request.action = "invoke";
	    request.funcInfo = funcInfo;

	    return Cryptokit.SendMessage(this.browser, request);
	}


	Cryptokit.prototype.GetLastErrorDesc = function () {

	    var request = new Object();
	    var funcInfo = new Object();
	    var randomId = GenerateRandomId();

	    funcInfo.function = "GetLastErrorDesc";
	    funcInfo.params = null;
	    funcInfo.randomId = randomId;

	    request.action = "invoke";
	    request.funcInfo = funcInfo;

	    return Cryptokit.SendMessage(this.browser, request);
	}